from charmicat.event_filter import Cut

    # opts.by_name
    # opts.cutsets
    # opts.by_cl
    # opts.exclude
    # opts.replace
    # opts.start_on
    # opts.intersection

class CutInterface(object):
    def cut(self, module):
        pass

class NameArg(CutInterface):
    def __init__(self, name):
        self.name = name
        
    def cuts(self, module):
        if self.name not in module.cuts:
            msg = "Cut `{}' not present in {}.cuts"
            raise KeyError(msg.format(self.name, module.__name__))
        
        cs_names = module.cuts[self.name]

        if len(cs_names) > 1:
            msg = "Cut named `{}' present in multiple cutsets: "
            msg += ', '.join(cs_names)
            raise NotImplementedError(msg)

        csn = list(cs_names)[0]

        for c in module.cutsets[csn]:
            if c.name == self.name:
                return [c]
        
class CLCutArg(CutInterface):
    def __init__(self, pos_str):
        self.pos_str = pos_str
        
    def cuts(self, module):
        return [Cut(name=self.pos_str,
                    pos_str=self.pos_str,
                    condvars=module.params)]
        
class CutsetArg(CutInterface):
    def __init__(self, cs_name):
        self.name = cs_name
    
    def cuts(self, module):
        if self.name not in module.cutsets:
            msg = "Cutset `{}' not present in module {}"
            raise KeyError(msg.format(self.name, module.__name__))

        return module.cutsets[self.name]


class CLCutCollection(object):
    '''Command-line cut collection'''

    def __init__(self, cl=[]):
        self._cl = []
        self._names = []
        for c in cl:
            self.add(c)
            
        self._intersect = False
        self._args = []
        self._replace = []
        self._exclude = []
        self.start_on = None

    def add(self, c):
        if type(c) == type('howdy!'):
            c = Cut(name=c,
                    pos_str=c)            

        self._cl.append(c)
        self._names.append(c.name)

    def cut_list(self, module):            
        for arg in self._args:
            for c in arg.cuts(module):
                self.add(c)        

        if len(self) == 0:
            csn = module.default_cutset
            for c in module.cutsets[csn]:
                self.add(c)

        if self.start_on is not None:
            index = self._names.index(self.start_on)
            self._cl = self._cl[index:]
            self._names = self._names[index:]
            
        for name in self._exclude:
            index = self._names.index(name)
            del self._names[index]
            del self._cl[index]        

        for src_name, na in self._replace:
            for i in xrange(len(self._cl)):
                if src_name == self._cl[i]:
                    self._cl[i] = na.cut(module)[0]
                    self._names[i] = self._cl[i].name
            
        if self._intersect:
            name = 'intersection of '
            name += ' and '.join([c.name for c in self._cl])
            pos_str = ' & '.join(['({0})'.format(c.pos_str) for c in self._cl])
            condvars = {}
            for c in self._cl:
                condvars.update(c.condvars)

            return [Cut(name=name, pos_str=pos_str, condvars=condvars)]
        else:
            return self._cl[:]                    

                   
    def cb_intersect(self, opt, optstr, value, op):
        setattr(op.values, opt.dest, True)
        self._intersect = True               

    def cb_by_name(self, opt, optstr, value, op):
        self._setoptlist(opt, value, op)

        self._args.append(NameArg(value))
    
    def cb_cutsets(self, opt, optstr, value, op):
        self._setoptlist(opt, value, op)

        self._args.append(CutsetArg(value))

    def cb_by_cl(self, opt, optstr, value, op):
        self._setoptlist(opt, value, op)

        self._args.append(CLCutArg(value))

    def cb_exclude(self, opt, optstr, value, op):
        self._setoptlist(opt, value, op)

        self._exclude.append(value)

    def cb_replace(self, opt, optstr, value, op):
        self._setoptlist(opt, value, op)

        opt.dest.append(value)
        
        src, dest = value.split('=')
        self._replace.append((src, NameArg(dest)))

    def cb_start_on(self, opt, optstr, value, op):
        setattr(op.values, opt.dest, value)
        self.start_on = value


    def _setoptlist(self, opt, value, op):
        if hasattr(op.values, opt.dest):
            getattr(op.values, opt.dest).append(value)
        else:
            setattr(op.values, opt.dest, [value])

    def __len__(self):
        return len(self._cl)
